Introduction

In this reading, you will refresh your memory on storing and displaying data with the help of UI elements and core data.

To obtain more information about working with Core Data, review the following learning materials from the Working with data in iOS course:

First, core data is a way to persist or cache data on a single Apple device. In prior courses, you learned that core data is used to save permanent data for offline use, cache temporary data and add undo functionality to apps on a single device. Core data is not just a database management system, it's also deeply tied to the user interface.

Second, relationships allow you to link entities. For example, creating a relationship between drinks and restaurants allows you to identify which drinks are served by a particular restaurant location or which location a drink is served at.

Let's go through some code examples of how this is implemented in practice.

UI elements and storing data example

In the case of the Little Lemon restaurant app, you retrieve a food menu from a remote server and receive an element formatted in JSON, in the following format:

{ 
  "menu": [ 
    { 

      "name": "Greek Salad", 
      "price": 12.99, 
      "description": "Our delicious salad is served with Feta cheese and peeled cucumber. Includes tomatoes, onions, olives, salt and oregano in the ingredients.", 
      "image": "greekSalad.jpg", 
    }, 
    { 
      "name": "Bruschetta", 
      "price": 7.99, 
      "description": "Delicious grilled bread rubbed with garlic and topped with olive oil and salt. Our Bruschetta includes tomato and cheese.", 
      "image": "bruschetta.jpg" 
    }, 
    { 
      "name": "Grilled Fish", 
      "price": 20.00, 
      "description": "Fantastic grilled fish seasoned with salt.", 
      "image": "grilledFish.jpg" 
    } 
  ] 
} 

As soon as the JSON is retrieved from the server, you must convert it to a suitable Swift format using the following structs.

To do that, first create structs to represent the data, like the following ones:

struct JSONMenu: Codable { 
    let menu: [MenuItem]     
} 


struct MenuItem: Codable { 
    let name: String 
    let price: Float 
    let description: String 
    let image: String 
} 

Then, retrieve the data and decode it using the defined structs.

      let (data, _) = try await urlSession.data(from: url)  
      let fullMenu = try JSONDecoder().decode(JSONMenu.self, from: data) 
      menuItems = fullMenu.menu 

The result, which is menuItems in this code, is an array of MenuItems .

For more information, please review the reading Exemplar: Little Lemon menu app in the Working with Data in iOS course.

The next phase is to convert these items into the format used by the entity Dish . Note that MenuItems has four properties: name , price , description , and image . These are exactly the same properties as Dish .

To do that, add a function to the Dish extension class to do this:

static func createDishesFrom(menuItems:[MenuItem], 
                                 _ context:NSManagedObjectContext) { 
        for menuItem in menuItems { 
            guard let _ = exists(name: menuItem.title, context) else { 
                continue 
            } 
            let oneDish = Dish(context: context) 
            oneDish.name = menuItem.title 
            if let price = Float(menuItem.price) { 
                oneDish.price = price 
            } 
            oneDish.dishDescription = menuItem.description 
            oneDish.image = menuItem.image 
        } 
    } 

This code takes the array of MenuItems and creates dishes in the Dish entity populating them with properties from the MenuItems .

For more information, please review the reading Displaying the food menu via core data in the Working with Data in iOS course.

After properly storing the data in core data, you have to retrieve it and show it in a list.

You may recall using code similar to the snippet below to achieve that:

            NavigationView { 
                FetchedObjects( 
                    predicate:buildPredicate(), 
                    sortDescriptors: buildSortDescriptors()) { 
                        (dishes: [Dish]) in 
                        List { 
                            ForEach(dishes, id:\.self) { dish in 
                                DisplayDish(dish) 
                                    .onTapGesture { 
                                        showAlert.toggle() 
                                    } 
                            } 
                        } 
                        .searchable(text: $searchText, 
                                    prompt: "search...") 
                    } 
            } 

FetchedObjects is a struct that replaces @FetchRequest and serves to use dynamic predicates and sort descriptors.

This function calls two other ones: buildPredicate and buildSortDescriptors , which are respectively used to build dynamic predicates and sort descriptors.

The last line is a modifier called searchable , which adds a search box to the NavigationView .

For more information, please review the reading Exemplar: Little Lemon Menu App in the Working with Data in iOS course.

Conclusion

In this reading, you’ve recapped the key aspects of storing data from a remote server in core data and displaying them in a list.